From d05c4adbfb1dc84649a6469e887bf489dc90a8c8 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 4 Jul 2005 08:20:20 +0000 Subject: [PATCH] The patch extends the VMCS handling to support both 32-bit and 64-bit guests. Please apply. It also includes cleanups. Signed-off-by: Jun Nakajima Signed-off-by: Chengyuan Li Signed-off-by: Yunhong Jiang --- xen/arch/x86/vmx_platform.c | 12 ++++---- xen/arch/x86/vmx_vmcs.c | 43 +++++++++++++++++++++++++---- xen/include/asm-x86/vmx_intercept.h | 2 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/vmx_platform.c index c2f7cd740f..bcf80e3d68 100644 --- a/xen/arch/x86/vmx_platform.c +++ b/xen/arch/x86/vmx_platform.c @@ -503,7 +503,7 @@ static int vmx_decode(const unsigned char *inst, struct instruction *thread_inst int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len) { - l1_pgentry_t gpte; + unsigned long gpa; unsigned long mfn; unsigned char *inst_start; int remaining = 0; @@ -513,8 +513,9 @@ int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_l if ( vmx_paging_enabled(current) ) { - gpte = gva_to_gpte(guest_eip); - mfn = phys_to_machine_mapping(l1e_get_pfn(gpte)); + gpa = gva_to_gpa(guest_eip); + mfn = phys_to_machine_mapping(gpa >> PAGE_SHIFT); + /* Does this cross a page boundary ? */ if ( (guest_eip & PAGE_MASK) != ((guest_eip + inst_len) & PAGE_MASK) ) { @@ -533,8 +534,9 @@ int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_l if ( remaining ) { - gpte = gva_to_gpte(guest_eip+inst_len+remaining); - mfn = phys_to_machine_mapping(l1e_get_pfn(gpte)); + gpa = gva_to_gpa(guest_eip+inst_len+remaining); + mfn = phys_to_machine_mapping(gpa >> PAGE_SHIFT); + inst_start = map_domain_page(mfn); memcpy((char *)buf+inst_len, inst_start, remaining); unmap_domain_page(inst_start); diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index fc2376ba76..3ec448f894 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -65,8 +65,12 @@ static inline int construct_vmcs_controls(void) error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, MONITOR_CPU_BASED_EXEC_CONTROLS); - +#if defined (__x86_64__) + error |= __vmwrite(VM_EXIT_CONTROLS, + MONITOR_VM_EXIT_CONTROLS | VM_EXIT_CONTROLS_IA_32E_MODE); +#else error |= __vmwrite(VM_EXIT_CONTROLS, MONITOR_VM_EXIT_CONTROLS); +#endif error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS); return error; @@ -93,6 +97,11 @@ struct host_execution_env { unsigned long tr_base; unsigned long ds_base; unsigned long cs_base; +#ifdef __x86_64__ + unsigned long fs_base; + unsigned long gs_base; +#endif + /* control registers */ unsigned long cr3; unsigned long cr0; @@ -230,8 +239,8 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs, /* interrupt */ error |= __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); /* mask */ - error |= __vmwrite(CR0_GUEST_HOST_MASK, 0xffffffff); - error |= __vmwrite(CR4_GUEST_HOST_MASK, 0xffffffff); + error |= __vmwrite(CR0_GUEST_HOST_MASK, -1UL); + error |= __vmwrite(CR4_GUEST_HOST_MASK, -1UL); error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); @@ -298,9 +307,19 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs, shadow_cr &= ~X86_CR0_PG; error |= __vmwrite(CR0_READ_SHADOW, shadow_cr); /* CR3 is set in vmx_final_setup_guest */ +#ifdef __x86_64__ + error |= __vmwrite(GUEST_CR4, host_env->cr4 & ~X86_CR4_PAE); + printk("construct_init_vmcs_guest: guest CR4 is %lx\n", host_env->cr4 ); +#else error |= __vmwrite(GUEST_CR4, host_env->cr4); +#endif shadow_cr = host_env->cr4; + +#ifdef __x86_64__ + shadow_cr &= ~(X86_CR4_PGE | X86_CR4_VMXE | X86_CR4_PAE); +#else shadow_cr &= ~(X86_CR4_PGE | X86_CR4_VMXE); +#endif error |= __vmwrite(CR4_READ_SHADOW, shadow_cr); error |= __vmwrite(GUEST_ES_BASE, host_env->ds_base); @@ -339,16 +358,24 @@ static inline int construct_vmcs_host(struct host_execution_env *host_env) error |= __vmwrite(HOST_ES_SELECTOR, host_env->ds_selector); error |= __vmwrite(HOST_SS_SELECTOR, host_env->ds_selector); error |= __vmwrite(HOST_DS_SELECTOR, host_env->ds_selector); +#if defined (__i386__) error |= __vmwrite(HOST_FS_SELECTOR, host_env->ds_selector); error |= __vmwrite(HOST_GS_SELECTOR, host_env->ds_selector); + error |= __vmwrite(HOST_FS_BASE, host_env->ds_base); + error |= __vmwrite(HOST_GS_BASE, host_env->ds_base); +#else + rdmsrl(MSR_FS_BASE, host_env->fs_base); + rdmsrl(MSR_GS_BASE, host_env->gs_base); + error |= __vmwrite(HOST_FS_BASE, host_env->fs_base); + error |= __vmwrite(HOST_GS_BASE, host_env->gs_base); + +#endif host_env->cs_selector = __HYPERVISOR_CS; error |= __vmwrite(HOST_CS_SELECTOR, host_env->cs_selector); host_env->ds_base = 0; host_env->cs_base = 0; - error |= __vmwrite(HOST_FS_BASE, host_env->ds_base); - error |= __vmwrite(HOST_GS_BASE, host_env->ds_base); /* Debug */ __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory"); @@ -366,6 +393,12 @@ static inline int construct_vmcs_host(struct host_execution_env *host_env) host_env->cr4 = crn; error |= __vmwrite(HOST_CR4, crn); error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler); +#ifdef __x86_64__ + /* TBD: support cr8 for 64-bit guest */ + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0); + __vmwrite(TPR_THRESHOLD, 0); + __vmwrite(SECONDARY_VM_EXEC_CONTROL, 0); +#endif return error; } diff --git a/xen/include/asm-x86/vmx_intercept.h b/xen/include/asm-x86/vmx_intercept.h index ab54682b2a..9465a7147b 100644 --- a/xen/include/asm-x86/vmx_intercept.h +++ b/xen/include/asm-x86/vmx_intercept.h @@ -8,7 +8,7 @@ #include #include -#define MAX_IO_HANDLER 6 +#define MAX_IO_HANDLER 10 typedef int (*intercept_action_t)(ioreq_t*); -- 2.30.2